package telas.componentes;

import javax.swing.FocusManager;
import javax.swing.JComboBox;
import business.sistema.ExceptionSistema;
import business.sistema.IObjetoSistema;
import business.sistema.Observer;
import business.sistema.Subject;
import java.awt.Dimension;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ComboGeral extends JComboBox implements Subject, Observer
{
	private static final long serialVersionUID = 6056333376133310876L;
	private ArrayList<IObjetoSistema> listaObjetos;
	private String metodoIdentificador = "";
	private String primeiroItem = TODOS;
	private ArrayList<Observer> observadores;
	private String metodoObterLista = "";
	private String metodoDescricao = "";
	
	/* Constantes */
	public static String SELECIONE = "Selecione";
	public static String TODOS = "Todos";
	
	/**
	 * Construtor
	 */
	public ComboGeral() 
	{
		super();
		initialize();
	}

	/**
	 * Inicializa
	 */
	private void initialize() 
	{
        this.setSize(new Dimension(150, 25));		
        
        this.addKeyListener
        (
        	new java.awt.event.KeyAdapter() 
	        {
	        	public void keyTyped(java.awt.event.KeyEvent e) 
	        	{
	        		char tecla = e.getKeyChar();
	        		
	        		if(tecla == '\n')
	        		{
	        			FocusManager.getCurrentManager().focusNextComponent();
	        		}
	        	}
	        }
        );
	}
	
	/**
	 * Método responsável por adicionar os objetos dentro do ComboBox
	 * 
	 * @param dados : List<IObjetoSistema>
	 */
	public void setDataSource(List<IObjetoSistema> dados)
	{
		listaObjetos = new ArrayList<IObjetoSistema>();
		IObjetoSistema primeiroObjeto = null;
		Method objMetodo = null;
		
		try
		{	
			// Limpa o Combo
			this.removeAllItems();
			
			// Matém o primeiro ítem no combo
			listaObjetos.add(primeiroObjeto);
			this.addItem(primeiroItem);
			
			for(IObjetoSistema objeto : dados)
			{
				listaObjetos.add(objeto);
			}
			
			for(int i = 0; i < dados.size(); i++)
			{
				Object objDados = dados.get(i);
				Class<?> objClasse = objDados.getClass();
				
				/* Nome */
				objMetodo = objClasse.getMethod(getMetodoDescricao());
				this.addItem(((String)objMetodo.invoke(objDados)));
			}
		}
		catch(Exception ex)
		{
			new ExceptionSistema(ex);
		}
	}
	
	public IObjetoSistema getObjetoCorrente()
	{
		IObjetoSistema objeto = null;
		
		if ( (listaObjetos.size() > 0) && 
			 (this.getSelectedIndex() > -1) )
			objeto = listaObjetos.get(this.getSelectedIndex());
		
		return objeto;
	}
	
	public void setObjetoCorrente(IObjetoSistema objetoSelecao)
	{
		Method metodo = null;
		int identificadorObjetoLista = 0;
		int identificadorObjetoSelecao = 0;
		
		try
		{
			Class<?> classe = objetoSelecao.getClass();
			metodo = classe.getMethod(getMetodoIdentificador());
			identificadorObjetoSelecao = (Integer)metodo.invoke(objetoSelecao);
			
			for(int i = 0; i < listaObjetos.size(); i++)
			{
				IObjetoSistema objeto = listaObjetos.get(i);
				if( objeto != null)
				{
					classe = objeto.getClass();
					metodo = classe.getMethod(getMetodoIdentificador());
					identificadorObjetoLista = (Integer)metodo.invoke(objeto);
					
					if(identificadorObjetoLista == identificadorObjetoSelecao)
					{
						setSelectedIndex(i);
						break;
					}
				}
			}
		}
		catch(Exception ex)
		{
			new ExceptionSistema(ex);
		}
	}
	
	public void limpar()
	{
		if(getItemCount() > 0)
			this.setSelectedIndex(0);
	}

	public String getMetodoIdentificador() 
	{
		return metodoIdentificador;
	}

	public void setMetodoIdentificador(String metodoIdentificador)
	{
		this.metodoIdentificador = metodoIdentificador;
	}

	public void setPrimeiroItem(String primeiroItem) 
	{
		this.primeiroItem = primeiroItem;
	}

	public void notifyObservers() throws Exception
	{
		for(Observer observador : getObservadores())
		{
			observador.update(getObjetoCorrente(),"");
		}
	}

	public void registerObserver(Observer observer) 
	{
		getObservadores().add(observer);
	}

	public void removeObserver(Observer observer) 
	{
		getObservadores().remove(observer);
	}

	private ArrayList<Observer> getObservadores() 
	{
		if(observadores == null)
		{
			observadores = new ArrayList<Observer>();
		}
		
		return observadores;
	}

	@SuppressWarnings("unchecked")
	public void update(IObjetoSistema objeto, String mensagem) throws Exception 
	{
		Method objMetodo = null;
		Class<?> objClasse = objeto.getClass();
		ArrayList<IObjetoSistema> listaObjetos = new ArrayList<IObjetoSistema>();
		
		objMetodo = objClasse.getMethod(getMetodoObterLista());
		
		Object listaObjeto = objMetodo.invoke(objeto);

		for(IObjetoSistema objetoSistema : (Set<IObjetoSistema>)listaObjeto)
		{
			listaObjetos.add(objetoSistema);
		}
		
		setDataSource(listaObjetos);
	}

	public String getMetodoObterLista() 
	{
		return metodoObterLista;
	}

	public void setMetodoObterLista(String metodoObterLista) 
	{
		this.metodoObterLista = metodoObterLista;
	}

	public String getMetodoDescricao() 
	{
		return metodoDescricao;
	}

	public void setMetodoDescricao(String metodoDescricao) 
	{
		this.metodoDescricao = metodoDescricao;
	}
}
